package com.ahwei.order.controller;


import com.ahwei.common.rest.base.R;
import com.ahwei.common.rest.base.ResultCode;
import com.ahwei.common.rest.exception.ApplicationException;
import com.ahwei.common.rest.exception.ResourceNotFoundException;
import com.ahwei.order.api.dto.OrderDto;
import com.ahwei.order.convert.OrderConvert;
import com.ahwei.order.entity.Order;
import com.ahwei.order.service.OrderService;
import com.ahwei.product.api.dto.ProductDto;
import com.ahwei.product.api.feign.RemoteProductService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author ahwei
 * @since 2022-05-26
 */
@Slf4j
@RestController
@RequestMapping("/api/order")
public class OrderController {
    @Autowired
    private OrderService orderService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 只要直接注入添加@FeignClient注解的接口，就可以直接调用远程服务。
     */
    @Autowired
    private RemoteProductService productService;

    @Autowired
    private ObjectMapper objectMapper;


    /**
     * 新增数据
     *
     * @return 新增结果
     */
    @PostMapping
    @GlobalTransactional(rollbackFor = Exception.class)
    @Operation(summary = "新增数据", description = "新增数据", parameters = {
            @Parameter(name = "productId", description = "商品id", in = ParameterIn.QUERY, schema = @Schema(implementation = Long.class)),
            @Parameter(name = "quantity", description = "数量", in = ParameterIn.QUERY, schema = @Schema(implementation = Integer.class)),
            @Parameter(name = "userId", description = "用户id", in = ParameterIn.QUERY, schema = @Schema(implementation = Long.class))})
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "操作成功", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = R.class))}),})
    @ResponseStatus(HttpStatus.CREATED)
    public R<Object> save(Long productId, Integer quantity, Long userId) throws JsonProcessingException {
        log.info("\n==> 客户下单，productId:'{}'调用商品微服务查询商品信息", productId);
        //获取商品信息
        ProductDto productDto = productService.getById(productId).getData();

        if (productDto.getStock() == 0) {
            throw new ApplicationException("库存不足！");
        }

        //先扣除库存，避免库存不足时
        productService.reduceInventory(productId,quantity);
        log.info("\n==> 查询productId:'{}'商品信息,查询结果:{}", productId, objectMapper.writeValueAsString(productDto));
        //获取用户信息

        //创建订单
        Order order = new Order();
        order.setUserId(1L);
        order.setProductId(1L);
        order.setNumber(quantity);
        order.setProductName(productDto.getName());
        order.setProductPrice(productDto.getPrice());
        order.setUserName("qwe");

        //返回结果
        boolean save = orderService.save(order);
        if (save){
            log.info("\n==> 创建订单成功,订单信息为:{}" + objectMapper.writeValueAsString(order));
            OrderDto orderDto = OrderConvert.INSTANCE.entity2dto(order);
            // 下单成功后发送消息到mq。第一个参数是topic或topic:tag，第二个参数是消息体
            rocketMQTemplate.convertAndSend("order-topic:tag1",orderDto);
            return R.ok("下单成功！",orderDto);
        }
        throw new ApplicationException("下单失败！");
    }



    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Operation(summary = "通过ID查询单条数据", description = "通过ID查询单条数据", parameters = {
            @Parameter(name = "id", description = "唯一标识", in = ParameterIn.QUERY, schema = @Schema(implementation = Integer.class))})
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "操作成功", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = R.class))}), @ApiResponse(responseCode = "404", description = "未找到相关信息",content = {@Content(mediaType = "application/json", schema = @Schema(implementation = R.class))})})
    @GetMapping("/{id}")
    public R<OrderDto> getById(@PathVariable("id") Long id) {
        Order order = orderService.getById(id);
        // 如果没有数据，就抛异常没有找到资源
        if (null != order) {
            OrderDto orderDto = OrderConvert.INSTANCE.entity2dto(order);
            return R.ok(orderDto);
        }

        throw new ResourceNotFoundException("未找到相关信息！");
    }


    /**
     * 更新数据
     *
     * @return 更新结果
     */
    @PutMapping()
    @Operation(summary = "更新数据", description = "更新数据", parameters = {
            @Parameter(name = "order", description = "更新信息", in = ParameterIn.QUERY, schema = @Schema(implementation = Order.class))})
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "操作成功", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = R.class))}),})
    @ResponseStatus(HttpStatus.OK)
    public R<Object> update(@Valid @RequestBody OrderDto orderDto) {
        //将OrderDto转为Order
        Order order = OrderConvert.INSTANCE.dto2entity(orderDto);

        boolean update = orderService.updateById(order);
        if (update){
            return R.ok(ResultCode.SUCCESS,"更新成功！");
        }
        throw new ApplicationException("更新失败！");
    }

    /**
     * 删除数据
     *
     * @param id 主键
     * @return 删除是否成功
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除数据", description = "删除数据", parameters = {
            @Parameter(name = "id", description = "唯一标识", in = ParameterIn.QUERY, schema = @Schema(implementation = List.class))})
    public R<Object> remove(@PathVariable("id") List<Long> id) {
        boolean remove = orderService.removeByIds(id);
        if (remove) {
            return R.ok(ResultCode.SUCCESS,"删除成功！");
        }
        throw new ApplicationException("删除失败！");
    }
}

